home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / drivers / mscdex / hitachi / mscdex.asm < prev    next >
Encoding:
Assembly Source File  |  1990-10-15  |  62.0 KB  |  1,975 lines

  1. ; ***************************************************************************
  2. ; *                                                                         *
  3. ; * MSCDEX.ASM                                                              *
  4. ; *                                                                         *
  5. ; * C D - R O M Device Driver Hardware Independent Interface.               *
  6. ; *                                                                         *
  7. ; * This file defines the hardware independent interface to the valid CD-ROM*
  8. ; * device driver commands defined in the document "Microsoft MS-DOS CD-ROM *
  9. ; * Extensions Hardware-Dependent Device Driver Specification",             *
  10. ; * #000080010-100-O00-1186.  The implementation of a MSCDEX CD-ROM device  *
  11. ; * driver will include this file verbatim.                                 *
  12. ; *                                                                         *
  13. ; * History:                                                                *
  14. ; *                                                                         *
  15. ; * Created (v2.20)                                                         *
  16. ; *     Fri Jun 22 1990  -by- Michael Edwards                               *
  17. ; * Modified (v2.20)                                                        *
  18. ; *     10/1/90 -by- JohnYG                                                 * 
  19. ; *     Final Release (v2.20)                                               *
  20. ; *                                                                         *
  21. ; *                                                                         *
  22. ; ***************************************************************************
  23.  
  24.         include mscdex.inc
  25.         include macros.mac
  26.  
  27.  
  28.         public  bcd2red
  29.         public  red2hsg
  30.         public  hsg2red
  31.         public  bcd2bin
  32.  
  33.         public  DeviceHeader
  34.         public  units
  35.         public  very_end
  36.  
  37.         extrn   cdrom_read              : near
  38.         extrn   cdrom_prefetch          : near
  39.         extrn   cdrom_seek              : near
  40.         extrn   cdrom_play_audio        : near
  41.         extrn   cdrom_stop_audio        : near
  42.         extrn   cdrom_location_head     : near
  43.         extrn   cdrom_audio_channel_info: near
  44.         extrn   cdrom_read_drive_bytes  : near
  45.         extrn   cdrom_device_status     : near
  46.         extrn   cdrom_volume_size       : near
  47.         extrn   cdrom_media_changed     : near
  48.         extrn   cdrom_audio_diskinfo    : near
  49.         extrn   cdrom_audio_diskinfo    : near
  50.         extrn   cdrom_audio_trackinfo   : near
  51.         extrn   cdrom_audio_Qchannel    : near
  52.         extrn   cdrom_audio_Subchannel  : near
  53.         extrn   cdrom_upc_code          : near
  54.         extrn   cdrom_audio_status_info : near
  55.         extrn   cdrom_eject             : near
  56.         extrn   cdrom_lock_door         : near
  57.         extrn   cdrom_reset_drive       : near
  58.         extrn   cdrom_audio_channel_ctrl: near
  59.         extrn   cdrom_write_drive_ctrl  : near
  60.         extrn   cdrom_close_tray        : near
  61.         extrn   cdrom_input_flush       : near
  62.         extrn   cdrom_input_flush       : near
  63.         extrn   cdrom_device_open       : near
  64.         extrn   cdrom_device_close      : near
  65.         extrn   cdrom_current_loc       : near
  66.         extrn   cdrom_drive_status      : near
  67.         extrn   cdrom_audio_check       : near
  68.         extrn   cdrom_init              : near
  69.  
  70. _TEXT   segment byte public 'CODE'
  71.         assume  cs:_TEXT
  72.  
  73. ;
  74. ; device drivers originate at 0 (not 100h)
  75. ;
  76.         org     0
  77.  
  78. very_top        label   byte
  79. ;
  80. ;  First character Device header (must be at offset 0)
  81. ;
  82. DeviceHeader:
  83.         dw      -1, -1                  ;pointer to next device
  84.         dw      0c800h                  ;(character, IOCTL, Open/Close/RM)
  85.         dw      strategy                ;strategy  routine offset
  86.         dw      interrupt               ;interrupt routine offset
  87.         db      '12345678'              ;device name (must be 8 valid chars)
  88.         dw      0                       ;reserved
  89.         db      0                       ;drive letter
  90. units   db      1                       ;number of units
  91.  
  92. RequestHeader:
  93.         dd      0                       ;strategy keeps request header ptr here
  94. ;
  95. ; Standard DOS device driver functions
  96. ;
  97. DriverFuncs:
  98.         dw      error                   ;*INIT (via far jmp from interrupt)
  99.         dw      error                   ; Media Check
  100.         dw      error                   ; Get BPB
  101.         dw      ioctl_input             ;*IOCTL input
  102.         dw      error                   ; Input
  103.         dw      error                   ; Non-destructive Input
  104.         dw      error                   ; Input status
  105.         dw      input_flush             ;*Input Flush (Hitachi does nothing)
  106.         dw      error                   ; Output
  107.         dw      error                   ; Output with verify
  108.         dw      error                   ; Output Status
  109.         dw      error                   ; Output Flush
  110.         dw      ioctl_output            ;*IOCTL output
  111.         dw      device_open             ;*Device Open
  112.         dw      device_close            ;*Device Close
  113.         dw      error                   ; Removable Media
  114.         dw      error                   ; Output until Busy
  115. ;
  116. ; Extended CDROM device driver functions
  117. ;
  118.         dw      read_long               ;*READ LONG
  119.         dw      error                   ; READ LONG NON-BLOCKING (Reserved)
  120.         dw      prefetch                ;*READ LONG PREFETCH
  121.         dw      seek                    ;*SEEK
  122.         dw      play_audio              ;+PLAY
  123.         dw      stop_audio              ;+STOP PLAY
  124.         dw      error                   ; WRITE LONG
  125.         dw      error                   ; WRITE LONG VERIFY
  126.         dw      resume_audio            ;+RESUME AUDIO
  127. ;
  128. ; IOCTL INPUT sub-functions
  129. ;
  130. IOCTLInput:
  131.         dw      return_address          ; IOI_return_address
  132.         dw      location_head           ; IOI_location_head
  133.         dw      error                   ; IOI_ioquery
  134.         dw      error                   ; IOI_err_stats
  135.         dw      audio_channel_info      ; IOI_audio_info
  136.         dw      read_drive_bytes        ; IOI_read_drive_bytes_bytes
  137.         dw      device_status           ; IOI_device_statusus
  138.         dw      sector_size             ; IOI_ret_sectsize
  139.         dw      volume_size             ; IOI_ret_volsize
  140.         dw      media_changed           ; IOI_media_changed
  141.         dw      audio_diskinfo          ; IOI_audio_disk_info
  142.         dw      audio_trackinfo         ; IOI_audio_track_info
  143.         dw      audio_Qchannel          ; IOI_audio_qch_info
  144.         dw      audio_Subchannel        ; IOO_Audio_Subinfo
  145.         dw      upc_code                ; IOO_upc_code
  146.         dw      audio_status_info       ; IOO_audio_status_info
  147. ;
  148. ; IOCTL OUTPUT sub-functions
  149. ;
  150. IOCTLOutput:
  151.         dw      eject                   ; IOO_eject_disc
  152.         dw      lock_door               ; IOO_lock_door
  153.         dw      reset_drive             ; IOO_reset_drive
  154.         dw      audio_channel_ctrl      ; IOO_audio_channel_ctrl
  155.         dw      write_drive_ctrl        ; IOO_write_drive_ctrl
  156.         dw      close_tray              ; IOO_close_tray
  157.  
  158. opens           dw      0               ;number of unbalanced device open calls
  159. drive_num       dw      0               ;drive operation is requested on
  160. audio_start     dd      8 dup(0)        ;last starting play audio location
  161. audio_end       dd      8 dup(0)        ;last ending   play audio location
  162. play_mode       db      8 dup(0)        ;audio paused/playing flags
  163. init_done       db      0               ;boolean whether device is init'd
  164.  
  165.  
  166. ;======================================================================
  167. ;
  168. ; strategy
  169. ;
  170. ; Device Strategy routine.  Saves the pointer to the caller's request
  171. ; header structure for the subsequent call into interrupt below.
  172. ;
  173. ; Entry:
  174. ;   es:bx         - far ptr to the caller's request header.
  175. ;
  176. ; Exit:
  177. ;   RequestHeader - far ptr to the caller's request header.
  178. ;
  179. ;======================================================================
  180. strategy proc far
  181.  
  182.         mov     word ptr cs:RequestHeader.lo,bx
  183.         mov     word ptr cs:RequestHeader.hi,es
  184.         ret
  185.  
  186. strategy endp
  187.  
  188.  
  189. ;======================================================================
  190. ;
  191. ; interrupt
  192. ;
  193. ; Main entry point to the device interrupt handler.
  194. ;
  195. ; Entry:
  196. ;   RequestHeader - far ptr to the caller's request header.
  197. ;       (see MSCDEX.INC) for format of the request header)
  198. ;
  199. ;======================================================================
  200. interrupt proc far
  201.  
  202.         push    ax
  203.         push    bx
  204.         push    cx
  205.         push    dx
  206.         push    si
  207.         push    di
  208.         push    bp
  209.         push    ds
  210.         push    es
  211. ;
  212. ; point ds:bx at the request header
  213. ;
  214.         lds     bx,dword ptr cs:RequestHeader
  215.  
  216.         mov     al,[bx].rqh_unit        ;al gets drive number
  217.         cbw
  218.         mov     cs:drive_num,ax         ;Save drive number
  219.  
  220.         mov     si,offset DriverFuncs
  221.         mov     al,[bx].rqh_cmd         ;get command
  222.         cmp     al,DVRQ_NCMD_MAX        ;extended command?
  223.         jbe     ok_cmd                  ;  nope
  224. ; must be extended cdrom device driver command, convert into index at
  225. ; end the normal cdrom device driver function table
  226.     cmp    al,DVRQ_ECMD_MIN
  227.     jb    @f
  228.         sub     al,(DVRQ_ECMD_MIN - DVRQ_NCMD_MAX - 1)
  229.         cmp     al,(DVRQ_NCMD_MAX + DVRQ_ECMD_MAX - DVRQ_ECMD_MIN + 1)
  230.         jbe     ok_cmd                  ;  yes
  231. @@:
  232.         jmp     error                   ;  nope, command out of range
  233.  
  234. ok_cmd:
  235.         cbw
  236.         shl     ax,1
  237.         add     si,ax
  238.         or      ax,ax                   ;init time?
  239.         jz      @f                      ;  yes
  240.                                         ;  no, dispatch to command
  241. dispatch_to_command:
  242.         jmp     word ptr cs:[si]
  243. @@:                                     ;being loaded from config.sys?
  244.         mov     al,1
  245.         xchg    cs:init_done,al
  246.         or      al,al
  247.         jnz     dispatch_to_command     ;  no, jmp to error
  248.         jmp     far ptr init            ;  yes, do init
  249.  
  250.  
  251. ;======================================================================
  252. ;
  253. ; read_long
  254. ;
  255. ; READ LONG, extended CD-ROM device driver routine to read sectors.
  256. ;
  257. ; Entry:
  258. ;   ds:bx - far ptr to the request header.
  259. ;
  260. ;======================================================================
  261. read_long:
  262.  
  263.         WriteAux <read_long>
  264.  
  265.         call    prepare_read_prefetch
  266.  
  267.         or      cx,cx                   ;number of sectors to read
  268.         jne     @f
  269.         mov     ax,drverr_read_fault    ;what? nothing to read!
  270.         jmp     short read_error
  271. @@:
  272. ;
  273. ; dl:ax - redbook address for read
  274. ;    cx - number of sectors to read
  275. ; es:bx - transfer address for data
  276. ;    dh - drive number (0 based)
  277. ;    di - read mode (0 = cooked, 1 = raw) 
  278. ;
  279.         call    cdrom_read              ;ask the device dependent code to read
  280.         jc      read_error              ;error occurred?
  281.         jmp     exit_not_busy           ;  nope
  282.  
  283. read_error:
  284.         jmp     exit                    ;  yep, status word's in ax
  285.  
  286.  
  287. ;======================================================================
  288. ;
  289. ; prefetch
  290. ;
  291. ; READ LONG PREFETCH, extended CD-ROM device driver routine to asynchronously
  292. ; read sectors into internal drive or driver controlled buffers.
  293. ;
  294. ; The cheap way to implement the prefetch command is with a seek since
  295. ; prefetching is considered advisory.  If a drive, or the driver software,
  296. ; implement a "read-ahead" buffer, this entry point would initiate filling
  297. ; the buffer, in anticipation of a subsequent READ LONG command from the
  298. ; same location.
  299. ;
  300. ; Entry:
  301. ;   ds:bx - far ptr to the caller's request header.
  302. ;
  303. ;======================================================================
  304. prefetch:
  305.  
  306.         WriteAux <prefetch>
  307.  
  308.         call    prepare_read_prefetch
  309. ;
  310. ; dl:ax - redbook address for read
  311. ;    cx - number of sectors to read
  312. ; es:bx - transfer address for data
  313. ;    dh - drive number (0 based)
  314. ;    di - read mode (0 = cooked, 1 = raw) 
  315. ;
  316.         call    cdrom_prefetch
  317.         jc      @f                      ;error occurred?
  318.         jmp     exit_not_busy           ;  no, return success
  319. @@:     jmp     exit                    ;  yep, status word's in ax
  320.  
  321.  
  322. ;======================================================================
  323. ;
  324. ; seek
  325. ;
  326. ; SEEK, extended CD-ROM device driver routine to asynchronously cause
  327. ; the drive head to seek to the passed location.
  328. ;
  329. ; Note if the drive, or driver, has control of any data buffers this
  330. ; command could be implemented as a READ operation.  In this way the
  331. ; data at the passed location would be buffered (in anticipation of a
  332. ; subsequent read request), and the drive head would end up "waiting"
  333. ; at the position where its buffers had filled.
  334. ;
  335. ; Entry:
  336. ;   ds:bx - far ptr to the caller's request header.
  337. ;
  338. ;======================================================================
  339. seek:
  340.  
  341.         WriteAux <seek>
  342.  
  343.         mov     ax,(ERRBIT + DONEBIT + BUSYBIT + drverr_general_failure)
  344.         call    check_if_busy           ;don't return if busy
  345. ;
  346. ; get sector to seek in dx:ax
  347. ;
  348.         mov     ax,word ptr rwl_sectno[si]
  349.         mov     dx,word ptr rwl_sectno[si+2]
  350.  
  351.         cmp     rwl_addrmd[si],MODE_RED ;redbook addressing mode ??
  352.         je      seek_redbook            ;  yes
  353.         cmp     rwl_addrmd[si],MODE_HSG ;  no, HSG addressing mode ??
  354.         je      seek_hsg                ;    yes
  355.         mov     ax,(ERRBIT + DONEBIT + drverr_unknown_command)
  356.         jmp     exit                    ;    no, return we don't understand
  357.  
  358. seek_redbook:
  359.         call    red2hsg
  360.  
  361. seek_hsg:
  362. ;
  363. ; Setup to seek to the desired block number
  364. ;
  365.         call    hsg2red                 ;dx:ax is HSG logical sector number
  366.         mov     dh,byte ptr cs:drive_num;dl = drive number
  367.         call    clear_audio_flags
  368. ;
  369. ; dl:ax - redbook address for read
  370. ;    dh - drive number (0 based)
  371. ;
  372.         call    cdrom_seek              ;ask the device dependent code to seek
  373.         jc      @f                      ;error occurred?
  374.         jmp     exit_not_busy           ;  no, return success
  375. @@:     jmp     exit                    ;  yep, status word's in ax
  376.  
  377.  
  378. ;======================================================================
  379. ;
  380. ; play_audio
  381. ;
  382. ; PLAY AUDIO, extended CD-ROM device driver routine to play the passed
  383. ; CD-Audio tracks.
  384. ;
  385. ; Note the busy bit in the request header must now indicate the drive
  386. ; is busy playing audio.  Also the starting/ending play locations and
  387. ; the audio paused flag must be initialized for use in pausing/resuming
  388. ; audio and reporting through the Audio Status info IOCTL Input
  389. ; fuction.
  390. ;
  391. ; Entry:
  392. ;   ds:bx - far ptr to the caller's request header.
  393. ;
  394. ;======================================================================
  395. play_audio:
  396.  
  397.         WriteAux <play_audio>
  398.  
  399.         mov     ax,(ERRBIT + DONEBIT + BUSYBIT + drverr_general_failure)
  400.         call    check_if_busy           ;don't return if busy
  401. ;
  402. ; get starting location from the PLAY command request header structure
  403. ;
  404.         mov     ax,wptr pl_start[si].lo
  405.         mov     dx,wptr pl_start[si].hi
  406. ;
  407. ; convert the starting address into hsg format if necessary
  408. ;
  409.         cmp     [si].pl_addrmd,MODE_RED
  410.         je      @f
  411.         cmp     [si].pl_addrmd,MODE_HSG
  412.         je      play_hsg
  413. ;
  414. ; don't understand requested play mode
  415. ;
  416.         mov     ax,(ERRBIT + DONEBIT + drverr_unknown_command)
  417.         jmp     exit
  418. @@:
  419.         call    red2hsg
  420.  
  421. play_hsg:
  422. ;
  423. ; save the HSG starting logical sector number
  424. ;
  425.         mov     bp,bx
  426.         shl     bp,1
  427.         shl     bp,1
  428.         mov     wptr cs:audio_start[bp].lo,ax
  429.         mov     wptr cs:audio_start[bp].hi,dx
  430.         mov     di,ax
  431.         mov     cx,dx
  432. ;
  433. ; determine and save the ending HSG locical sector number
  434. ;
  435.         add     ax,wptr pl_num[si].lo   ;get playing length
  436.         adc     dx,wptr pl_num[si].hi
  437.         mov     wptr cs:audio_end[bp].lo,ax
  438.         mov     wptr cs:audio_end[bp].hi,dx
  439.  
  440. play_start:
  441. ;
  442. ; this is also an entry point from RESUME AUDIO
  443. ;
  444. ; dx:ax - audio ending HSG logical sector number
  445. ; cx:di - audio start  HSG logical sector number
  446. ;    bx - drive number
  447. ;    bp - drive number * 4
  448. ;
  449.         call    cdrom_play_audio        ;ask device dependent code to play
  450.         jc      @f                                  ;was play successful?
  451.         mov     byte ptr cs:play_mode[bx],PLAY_TRUE ;  yes
  452.         jmp     exit_busy
  453. @@:                                                 ;  no
  454.         mov     byte ptr cs:play_mode[bx],PLAY_FALSE;reset playing mode flag
  455.         xor     cx,cx
  456.         mov     word ptr cs:audio_start[bp],cx      ;clear start and end..
  457.         mov     word ptr cs:audio_start[bp+2],cx    ;..locations
  458.         mov     word ptr cs:audio_end[bp],cx
  459.         mov     word ptr cs:audio_end[bp+2],cx
  460.         jmp     exit                                ;return error status in ax
  461.         
  462.  
  463. ;======================================================================
  464. ;
  465. ; stop_audio
  466. ;
  467. ; STOP AUDIO, extended CD-ROM device driver routine to pause or stop
  468. ; the CD-Audio tracks currently playing.
  469. ;
  470. ; Note the busy bit in the request header must now indicate the drive
  471. ; is no longer busy playing audio.  Also the audio paused flag must be
  472. ; set if this is the first STOP AUDIO command received since the last PLAY
  473. ; AUDIO or RESUME AUDIO command.  Otherwise (if this is the second
  474. ; STOP AUDIO command in a row) it must be cleared and the starting/ending 
  475. ; play locations must be zeroed.
  476. ;
  477. ; Entry:
  478. ;   ds:bx - far ptr to the caller's request header.
  479. ;
  480. ;======================================================================
  481. stop_audio:
  482.  
  483.         xor     ax,ax                   ;return if busy
  484.         call    check_if_busy           ;currently playing?
  485.         pushf
  486.         mov     bp,bx                   ;bx = drive num
  487.         shl     bp,1                    ;bp = drive num * 4
  488.         shl     bp,1
  489.         popf
  490.         jc      stop_audio_pause        ;   yep
  491.         jnc     stop_audio_stop         ;   nope
  492.  
  493. stop_audio_pause:
  494.  
  495.         WriteAux <pause_audio>
  496.  
  497. ;
  498. ; this is the first STOP AUDIO command received since last PLAY or RESUME
  499. ; AUDIO command, so reset the start location to current location, and
  500. ; set the audio paused flag
  501. ;
  502.         call    get_current_loc         ;get HSG logical sector at drive head
  503.         jc      stop_audio_stop
  504.         mov     word ptr cs:audio_start[bp],ax
  505.         mov     word ptr cs:audio_start[bp+2],dx
  506. ;
  507. ; make sure we havn't passed the ending location
  508. ;
  509.         cmp     dx,word ptr cs:audio_end[bp+2]
  510.         ja      stop_audio_stop
  511.         jb      @f
  512.         cmp     ax,word ptr cs:audio_end[bp]
  513.         ja      stop_audio_stop
  514. @@:     mov     byte ptr cs:play_mode[bx],PAUSE_TRUE
  515. ;
  516. ; tell the drive to stop playing audio.  if desired this can actually be
  517. ; implemented as a command to pause the head at the current location, but
  518. ; at any rate the audio will be resumed with a play audio command which
  519. ; passes the starting and ending locations to play (see resume_audio).
  520. ;
  521. stop_audio_exit:
  522.  
  523. ; bx - drive number to pause/stop audio on
  524. ;
  525.         call    cdrom_stop_audio
  526.         jnc     @f                      ;reset pause flag if error occurred
  527.         mov     byte ptr cs:play_mode[bx],PAUSE_FALSE
  528. @@:     jmp     exit_not_busy
  529.  
  530. stop_audio_stop:
  531. ;
  532. ; the drive is not already playing audio so we need to REALLY stop audio by
  533. ; clearing the audio paused flag and zeroing the starting/ending locations
  534. ;
  535.         WriteAux <stop_audio>
  536.  
  537.         xor     ax,ax
  538.         mov     word ptr cs:audio_start[bp],ax
  539.         mov     word ptr cs:audio_start[bp+2],ax
  540.         mov     word ptr cs:audio_end[bp],ax
  541.         mov     word ptr cs:audio_end[bp+2],ax
  542.         mov     byte ptr cs:play_mode[bx],PAUSE_FALSE
  543.         jmp     short stop_audio_exit
  544.  
  545.  
  546. ;======================================================================
  547. ;
  548. ; resume_audio
  549. ;
  550. ; RESUME AUDIO, extended CD-ROM device driver routine to resume playing
  551. ; CD-Audio tracks previously paused (by calling STOP AUDIO).
  552. ;
  553. ; Note the busy bit in the request header must now indicate the drive
  554. ; is busy playing audio.  Also the audio paused flag must be
  555. ; set if this is the first STOP AUDIO command received since the last PLAY
  556. ; AUDIO or RESUME AUDIO command.  Otherwise (if this is the second
  557. ; STOP AUDIO command in a row) it must be cleared and the starting/ending 
  558. ; play locations must be zeroed.
  559. ;
  560. ; Entry:
  561. ;   ds:bx - far ptr to the caller's request header.
  562. ;
  563. ;======================================================================
  564. resume_audio:
  565.  
  566.         WriteAux <resume_audio>
  567.  
  568.         mov     ax,(ERRBIT + DONEBIT + BUSYBIT + drverr_general_failure)
  569.         call    check_if_busy           ;don't return if busy
  570. ;
  571. ; make sure audio has been previously paused before try resuming!
  572. ;
  573.         cmp     cs:play_mode[bx],PAUSE_TRUE
  574.         mov     ax,(ERRBIT + DONEBIT + drverr_general_failure)
  575.         jne     resume_error
  576. ;
  577. ; ask device dependent code if the drive is able to resume audio now
  578. ;
  579.         call    get_drive_status
  580.         mov     ax,(ERRBIT + DONEBIT + drverr_drive_not_ready)
  581.         jc      resume_error
  582. ;
  583. ; setup registers for entry into the play audio command:
  584. ;
  585.         mov     bp,bx
  586.         shl     bp,1
  587.         shl     bp,1
  588.         mov     dx,word ptr cs:audio_end[bp+2]
  589.         mov     ax,word ptr cs:audio_end[bp]
  590.         mov     cx,word ptr cs:audio_start[bp+2]
  591.         mov     di,word ptr cs:audio_start[bp]
  592. ;
  593. ; dx:ax - audio ending HSG logical sector number
  594. ; cx:di - audio start  HSG logical sector number
  595. ;    bx - drive number
  596. ;    bp - drive number * 4
  597. ;
  598.         jmp     play_start
  599.  
  600. resume_error:
  601.         jmp     exit                    ;return error status in ax
  602.  
  603.  
  604. ;======================================================================
  605. ;
  606. ; ioctl_input
  607. ;
  608. ; IOCTL INPUT, CD-ROM device driver routines to retrieve device information:
  609. ;
  610. ; - address of device header
  611. ; - location of head
  612. ; - error statistics
  613. ; - audio channel information
  614. ; - read drive bytes
  615. ; - device status
  616. ; - sector size
  617. ; - volume size
  618. ; - media changed
  619. ; - audio disk information
  620. ; - audio track information
  621. ; - audio Q-channel information
  622. ; - audio sub-channel information
  623. ; - audio status information
  624. ;
  625. ; Entry:
  626. ;       ds:bx - far ptr to the caller's request header.
  627. ;
  628. ; Dispatch to IOCTL input subfunctions:
  629. ;       es:di - application control block (xfer address) after command code
  630. ;          bx - drive number
  631. ;
  632. ;======================================================================
  633. ioctl_input:
  634.  
  635.         mov     si,offset IOCTLInput    ;ioctl input subfunction table
  636.         mov     dl,IOI_cmd_max          ;last ioctl input subfunction
  637.  
  638. ioctl_dispatch:
  639. ;
  640. ; dl contains the 0-based value of last valid sub-function number
  641. ; si points to the function dispatcher table
  642. ;
  643.         les     di,ioctl_xfer[bx]       ;application's transfer address
  644.         mov     al,es:[di]              ;get the sub-function command code..
  645.         inc     di                      ;..and point just past it
  646.         cmp     al,dl                   ;out of bounds?
  647.         jbe     @f                      ;  no
  648.         jmp     error                   ;  yes
  649. @@:
  650.         cbw
  651.         shl     ax,1
  652.         add     si,ax
  653. ;
  654. ; dispatch point to IOCTL INPUT/OUTPUT sub-functions
  655. ;
  656.         mov     bx,cs:drive_num
  657.         jmp     word ptr cs:[si]        ;jump to the requested ioctl function
  658.  
  659.  
  660. ;======================================================================
  661. ;
  662. ; ioctl_output
  663. ;
  664. ; IOCTL OUTPUT, CD-ROM device driver routines relay for sending various
  665. ; commands to the drive to:
  666. ;
  667. ; - Eject Disk (open tray)
  668. ; - Lock/Unlock drive door
  669. ; - Reset drive
  670. ; - Audio Channel Control
  671. ; - Write device control string
  672. ; - Close tray
  673. ;
  674. ; Entry:
  675. ;   ds:bx - far ptr to the caller's request header.
  676. ;
  677. ; Dispatch to IOCTL output subfunctions:
  678. ;       es:di - application control block (xfer address) after command code
  679. ;          bx - drive number
  680. ;
  681. ;======================================================================
  682. ioctl_output:
  683.  
  684.         mov     si,offset IOCTLOutput   ;function dispatcher for IOCTL Output
  685.         mov     dl,IOO_cmd_max          ;number of IOCTL Output functions
  686.         jmp     short ioctl_dispatch    ;go to ioctl function dispatcher
  687.  
  688.  
  689. ioctl_io_exit:
  690. ;
  691. ; generic successful IOCTL INPUT/OUTPUT exit point
  692. ;
  693.         mov     ax,(DONEBIT + BUSYBIT)  ;don't return if busy
  694.         call    check_if_busy           ;bx != reqhead but don't need si..
  695.         jmp     exit_not_busy           ;..to point at the reqhead anyway
  696.  
  697.  
  698. ;============================================================
  699. ;
  700. ; IOCTL INPUT commands...
  701. ;
  702. ;============================================================
  703.  
  704. ;----------------------------------------------------------------------
  705. ;
  706. ; return_address
  707. ;
  708. ; IOCTL INPUT sub-function #0.
  709. ;
  710. ; Return the address of the device header.
  711. ;
  712. ;----------------------------------------------------------------------
  713. return_address:
  714.  
  715.         WriteAux <ioctl input return address>
  716.  
  717.         mov     word ptr es:[di].io_devaddr,offset DeviceHeader
  718.         mov     word ptr es:[di+2].io_devaddr,cs
  719.         jmp     short ioctl_io_exit
  720.  
  721.  
  722. ;----------------------------------------------------------------------
  723. ;
  724. ; location_head
  725. ;
  726. ; IOCTL INPUT sub-function #1
  727. ;
  728. ; Return the current location of the drive head.
  729. ;
  730. ;----------------------------------------------------------------------
  731. location_head:
  732.  
  733.         WriteAux <ioctl input location head>
  734.  
  735. ; ask the device driver to report on current head location
  736. ;
  737.         call    cdrom_location_head     ;preserves di
  738. ;
  739. ; if carry set
  740. ;   then an error occurred and the status word is in ax
  741. ; else 
  742. ;   dx:ax = HSG logical sector address of the drive head
  743. ;
  744.         jnc     @f
  745.         jmp     exit
  746. @@:
  747. ;
  748. ; we've got it in HSG, but do they want it returned in redbook?
  749. ;
  750.         cmp     es:io_loc_mode[di],MODE_HSG
  751.         je      location_head_hsg
  752.         cmp     es:io_loc_mode[di],MODE_RED
  753.         je      @f
  754.         jmp     error                   ;don't understand the addressing mode
  755.  
  756. location_head_hsg:
  757.         call    hsg2red
  758. @@:
  759.         mov     word ptr es:io_loc[di],ax
  760.         mov     word ptr es:io_loc[di+2],dx
  761.         jmp     ioctl_io_exit
  762.  
  763.  
  764. ;----------------------------------------------------------------------
  765. ;
  766. ; IOCTL INPUT sub-function #2
  767. ;
  768. ; This sub-function is currently reserved for future use.
  769. ;
  770. ;----------------------------------------------------------------------
  771.  
  772.  
  773. ;----------------------------------------------------------------------
  774. ;
  775. ; error_statistics
  776. ;
  777. ; IOCTL INPUT sub-function #3
  778. ;
  779. ; Report error statistics (currently not defined).
  780. ;
  781. ;----------------------------------------------------------------------
  782.  
  783.  
  784. ;----------------------------------------------------------------------
  785. ;
  786. ; audio_channel_info
  787. ;
  788. ; IOCTL INPUT sub-function #4
  789. ;
  790. ; Report current audio channel control settings.  This will be the default
  791. ; arrangement of 1:1 input to output at full volume, otherwise it's whatever 
  792. ; was last set by the Audio Channnel Control IOCTL Output subfunction #3.
  793. ;
  794. ; Note:
  795. ;   - if volume settings are limited to ON/OFF, then FFh is on, 0 is off.
  796. ;   - if the drive doesn't support quadrophonic then input channels 2 and 3
  797. ;     are assigned to output channels 0 and 1 with 0 volume.
  798. ;
  799. ;----------------------------------------------------------------------
  800. audio_channel_info:
  801.  
  802.         WriteAux <ioctl input audio channel info>
  803.  
  804. ; es:di - transfer area for audio channel info
  805. ; bx    - drive num to report on
  806. ;
  807.         call    cdrom_audio_channel_info
  808. ;
  809. ; returns with the applications parameter block setup:
  810. ;
  811. ;  es:[di+0] - current input channel set for output channel 0
  812. ;  es:[di+1] - current volume        set for output channel 0
  813. ;  es:[di+2] - current input channel set for output channel 1
  814. ;  es:[di+3] - current volume        set for output channel 1
  815. ;  es:[di+4] - current input channel set for output channel 2
  816. ;  es:[di+5] - current volume        set for output channel 2
  817. ;  es:[di+6] - current input channel set for output channel 3
  818. ;  es:[di+7] - current volume        set for output channel 3
  819. ;
  820.         jmp     ioctl_io_exit
  821.  
  822.  
  823. ;----------------------------------------------------------------------
  824. ;
  825. ; read_drive_bytes
  826. ;
  827. ; IOCTL INPUT sub-function #5
  828. ;
  829. ; Read device dependent information.  This routine is for accessing
  830. ; device specific features not addressed by the MSCDEX device driver spec.
  831. ;
  832. ;----------------------------------------------------------------------
  833. read_drive_bytes:
  834.  
  835.         WriteAux <ioctl input read drive bytes>
  836.  
  837. ;    bx - drive number
  838. ; es:di - 129 byte transfer address for drive specific data
  839. ;
  840.         call    cdrom_read_drive_bytes  ;sets es:[di+0] to num bytes xfered
  841.         jmp     ioctl_io_exit
  842.  
  843.  
  844. ;----------------------------------------------------------------------
  845. ;
  846. ; device_status
  847. ;
  848. ; IOCTL INPUT sub-function #6
  849. ;
  850. ; Return 32 bits of drive status information:
  851. ;
  852. ; 13 12 11 10 9 8 7 6 5 4 3 2 1 0       BIT SET                    BIT CLEAR
  853. ;  .  |  |  | | | | | | | | | | |                          |
  854. ; 31  |  |  | | | | | | | | | |  - door open               | door closed
  855. ;  |  |  |  | | | | | | | | | |                            |
  856. ;  |  |  |  | | | | | | | | |  --- door unlocked           | door locked
  857. ;  |  |  |  | | | | | | | | |                              |
  858. ;  |  |  |  | | | | | | | |  ----- cooked and raw mode     | cooked mode only
  859. ;  |  |  |  | | | | | | | |                                |
  860. ;  |  |  |  | | | | | | |  ------- read and write          | read only 
  861. ;  |  |  |  | | | | | | |                                  |
  862. ;  |  |  |  | | | | | |  --------- can play audio/video    | data read only 
  863. ;  |  |  |  | | | | | |                                    |
  864. ;  |  |  |  | | | | |  ----------- ISO-9660 interleave     | no interleaving 
  865. ;  |  |  |  | | | | |                                      |
  866. ;  |  |  |  | | | |  ------------- reserved                |
  867. ;  |  |  |  | | | |                                        |
  868. ;  |  |  |  | | |  --------------- prefetching support     | no prefetching 
  869. ;  |  |  |  | | |                                          |
  870. ;  |  |  |  | |  ----------------- audio chnls configurable| not configurable
  871. ;  |  |  |  | |                                            |
  872. ;  |  |  |  |  ------------------- HSG and redbook addr    | only HSG addr
  873. ;  |  |  |  |                                              |
  874. ;  |  |  |   --------------------- reserved                |
  875. ;  |  |  |                                                 |
  876. ;  |  |   ------------------------ no disc in drive        | disc in drive
  877. ;  |  |                                                    |
  878. ;  |   --------------------------- P-W subchan.  support   | no subchan. spt.
  879. ;  |
  880. ;   ------------------------------ reserved (all bits clear)
  881. ;----------------------------------------------------------------------
  882. device_status:
  883.  
  884.         WriteAux <ioctl input device status>
  885.  
  886. ; bx - drive number
  887. ;
  888.         call    cdrom_device_status
  889. ;
  890. ; returns status in dx:ax or carry set to indicate an error occurred
  891. ;
  892.         jc      @f
  893. ;
  894. ; set device status words in the application's space
  895. ;
  896.         mov     word ptr es:io_dev_params[di],ax
  897.         mov     word ptr es:io_dev_params[di+2],dx
  898.         jmp     ioctl_io_exit
  899. @@:
  900.         mov     ax,(ERRBIT + DONEBIT + drverr_drive_not_ready)
  901.         jmp     exit
  902.  
  903.  
  904.  
  905. ;----------------------------------------------------------------------
  906. ;
  907. ; sector_size
  908. ;
  909. ; IOCTL INPUT sub-function #7
  910. ;
  911. ; Return CD-ROM sector size for the passed read mode.  This must be
  912. ; 2048 for cooked, 2352 for raw.
  913. ;----------------------------------------------------------------------
  914. sector_size:
  915.  
  916.         WriteAux <ioctl input sector size>
  917.  
  918.         mov     ax,2048                         ;assume cooked mode
  919.         cmp     es:[di].io_sect_mode,IO_COOKED  ;cooked assumption correct?
  920.         je      @f                              ;  Yes
  921.         mov     ax,2352                         ;  nope, how about raw?
  922.         cmp     es:[di].io_sect_mode,IO_RAW
  923.         je      @f                              ;    yep
  924.         xor     ax,ax                           ;    nope, unknown I/O mode
  925. @@:     mov     es:[di].io_sect_size,ax
  926.         jmp     ioctl_io_exit
  927.  
  928.  
  929. ;----------------------------------------------------------------------
  930. ;
  931. ; volume_size
  932. ;
  933. ; IOCTL INPUT sub-function #8
  934. ;
  935. ; Return number of CD-ROM sectors available on the disc.  This is the 
  936. ; location of the lead out track in binary.  For example a lead-out track
  937. ; at 31:14.63 would yield (31 * 60 * 75) + (14 * 75) + 63 = 140613.
  938. ;----------------------------------------------------------------------
  939. volume_size:
  940.  
  941.         WriteAux <ioctl input volume size>
  942.  
  943. ; bx - drive number
  944. ;
  945.         call    cdrom_volume_size
  946.         jc      @f                      ;error getting size?
  947.         mov     word ptr es:[di].io_dev_params,ax
  948.         mov     word ptr es:[di+2].io_dev_params,dx
  949.         jmp     ioctl_io_exit
  950. @@:
  951.         xor     dx,dx                   ;  yes
  952.         mov     word ptr es:[di].io_dev_params,dx
  953.         mov     word ptr es:[di+2].io_dev_params,dx
  954.         jmp     exit                    ;return status word in ax
  955.  
  956.  
  957.  
  958. ;----------------------------------------------------------------------
  959. ;
  960. ; media_changed
  961. ;
  962. ; IOCTL INPUT sub-function #9
  963. ;
  964. ; Report whether the media has been changed.  This vastly improves file i/o
  965. ; performance because MSCDEX can avoid re-reading the VTOC unless the disc
  966. ; has actually been changed.
  967. ;
  968. ; Exit:
  969. ;      io_media byte =  1 - not changed
  970. ;      io_media byte = -1 - changed
  971. ;      io_media byte =  0 - can't determine if changed or not
  972. ;
  973. ;----------------------------------------------------------------------
  974. media_changed:
  975.  
  976.         WriteAux <ioctl input media changed>
  977.  
  978. ; bx = drive num
  979. ;
  980.         call    cdrom_media_changed
  981.         mov     es:io_media[di],al      ;set the media byte
  982.         jc      @f                      ;error occurred?
  983.         jmp     ioctl_io_exit
  984. @@:
  985.         mov     ax,(ERRBIT + DONEBIT + drverr_drive_not_ready)
  986.         jmp     exit                    ;  yep, get outta here
  987.  
  988.  
  989.  
  990.  
  991. ;----------------------------------------------------------------------
  992. ;
  993. ; audio_diskinfo
  994. ;
  995. ; IOCTL INPUT sub-function #10
  996. ;
  997. ; Report the binary value of the lowest and highest track, and the redbook
  998. ; address of the lead-out track as recorded in the Q-channel of the 
  999. ; lead-in track.
  1000. ;
  1001. ; In order to avoid interrupting audio to obtain this information it
  1002. ; is recommended the necessary values are saved at disc intialization time.
  1003. ;
  1004. ;----------------------------------------------------------------------
  1005. audio_diskinfo:
  1006.  
  1007.         WriteAux <ioctl input audio disk info>
  1008.  
  1009. ;    bx - drive num
  1010. ; es:di - application buffer for disk info
  1011. ;
  1012.         call    cdrom_audio_diskinfo
  1013.         jc      @f                      ;error occurred? 
  1014.         jmp     ioctl_io_exit
  1015. @@:     jmp     exit                    ;  yes, ax contains status
  1016.  
  1017.  
  1018. ;----------------------------------------------------------------------
  1019. ;
  1020. ; audio_trackinfo
  1021. ;
  1022. ; IOCTL INPUT sub-function #11
  1023. ;
  1024. ; Return the redbook address of the passed binary track number, and the
  1025. ; track control information byte.
  1026. ;
  1027. ;----------------------------------------------------------------------
  1028. audio_trackinfo:
  1029.  
  1030.         WriteAux <ioctl input audio track info>
  1031.  
  1032. ;    bx - drive num
  1033. ; es:di - application buffer for track info
  1034. ;        
  1035.         call    cdrom_audio_trackinfo
  1036.         jc      @f                      ;error occurred? 
  1037.         jmp     ioctl_io_exit
  1038. @@:     jmp     exit                    ;  yes, ax contains status
  1039.  
  1040.  
  1041. ;----------------------------------------------------------------------
  1042. ;
  1043. ; audio_Qchannel
  1044. ;
  1045. ; IOCTL INPUT sub-function #12
  1046. ;
  1047. ; Return the current Q-channel address in redbook.
  1048. ;
  1049. ; Note the operation of this function *should not* change the current
  1050. ; drive status, as it can be used to monitor the current head location.
  1051. ; Therefore, it should be successful even if the drive is currently idle.
  1052. ; Note the CONTROL/ADR and POINT/Index bytes are returned verbatim,
  1053. ; and if ADR is 1, so is the address of the head location.
  1054. ;
  1055. ;----------------------------------------------------------------------
  1056. audio_Qchannel:
  1057.  
  1058.         WriteAux <ioctl input audio Q channel>
  1059.  
  1060. ;    bx - drive num
  1061. ; es:di - application buffer for disk info
  1062. ;
  1063.         call    cdrom_audio_Qchannel
  1064.         jc      @f                      ;error occurred? 
  1065.         jmp     ioctl_io_exit
  1066. @@:     jmp     exit                    ;  yes, ax contains status
  1067.  
  1068.  
  1069.  
  1070. ;----------------------------------------------------------------------
  1071. ;
  1072. ; audio_Subchannel
  1073. ;
  1074. ; IOCTL INPUT sub-function #13
  1075. ;
  1076. ; Returns the sub-channel information from the contiguous frames (sectors)
  1077. ; requested starting at the passed redbook address.  The sub-channels are
  1078. ; not decoded, that is, P is the MSB and W is the LSB in each byte.
  1079. ;
  1080. ; The caller ensures the transfer address can hold 96 bytes/sector read.
  1081. ; The new definition indicates that P-W can only be accessed during audio
  1082. ; play requests.
  1083. ;----------------------------------------------------------------------
  1084. audio_Subchannel:
  1085.  
  1086.         WriteAux <ioctl input subchannel>
  1087.  
  1088. ;    bx - drive num
  1089. ; es:di - application buffer for sub-channel bytes
  1090. ;
  1091.         call    cdrom_audio_Subchannel
  1092.         jc      @f                      ;error occurred? 
  1093.         jmp     ioctl_io_exit
  1094. @@:     jmp     exit                    ;  yes, ax contains status
  1095.  
  1096.  
  1097. ;----------------------------------------------------------------------
  1098. ;
  1099. ; upc_code
  1100. ;
  1101. ; IOCTL INPUT sub-function #14
  1102. ;
  1103. ; Return the Universal Product Code of the disc.  This is located in 10
  1104. ; contiguous bytes of the Q-channel (ie., in one frame out of every 100),
  1105. ; and identified with an ADR value of 2.
  1106. ;
  1107. ; Note, not all discs have one.
  1108. ;
  1109. ;----------------------------------------------------------------------
  1110. upc_code:
  1111.  
  1112.         WriteAux <ioctl input UPC code>
  1113.  
  1114. ;    bx - drive num
  1115. ; es:di - application buffer for UPC bytes
  1116. ;
  1117.         call    cdrom_upc_code
  1118.         jc      @f                      ;error occurred? 
  1119.         jmp     ioctl_io_exit
  1120. @@:     jmp     exit                    ;  yes, ax contains status
  1121.  
  1122.  
  1123. ;----------------------------------------------------------------------
  1124. ;
  1125. ; audio_status_info
  1126. ;
  1127. ; IOCTL INPUT sub-function #15
  1128. ;
  1129. ; Return audio status information including whether audio is currently
  1130. ; paused and the starting and ending location for the latest PLAY or
  1131. ; RESUME AUDIO command.
  1132. ;----------------------------------------------------------------------
  1133. audio_status_info:
  1134.  
  1135.         WriteAux <ioctl input audio status info>
  1136.  
  1137. ;    bx - drive num
  1138. ; es:di - application buffer for status info
  1139. ;
  1140.         call    cdrom_audio_status_info ;is the drive door open?
  1141.         jc      @f                      ;  yes
  1142.         mov     al,cs:play_mode[bx]     ;  no
  1143.         test    al,(PAUSE_TRUE or PLAY_TRUE)
  1144.         jz      audio_status_info_null
  1145. ;
  1146. ; we're either paused or playing, in which case audio_start/end
  1147. ; contain the starting and ending (disc relative) times to report in the
  1148. ; audio status block (and play_mode has the paused flag)
  1149. ;
  1150.         and     ax,PAUSE_TRUE           ;isolate paused bit and make it..
  1151.         shr     ax,1                    ;..the LSB of the audio status word
  1152.         mov     word ptr es:io_audio_st_bit[di],ax
  1153.         shl     bx,1
  1154.         shl     bx,1
  1155.         mov     ax,word ptr cs:audio_start[bx]
  1156.         mov     dx,word ptr cs:audio_start[bx+2]
  1157.         call    hsg2red
  1158.         mov     word ptr es:io_audio_start[di],ax
  1159.         mov     word ptr es:io_audio_start[di+2],dx
  1160.         mov     ax,word ptr cs:audio_end[bx]
  1161.         mov     dx,word ptr cs:audio_end[bx+2]
  1162.         call    hsg2red
  1163.         mov     word ptr es:io_audio_end[di],ax
  1164.         mov     word ptr es:io_audio_end[di+2],dx
  1165.  
  1166. audio_status_info_exit:
  1167.         jmp     ioctl_io_exit
  1168.  
  1169. @@:      
  1170. ;
  1171. ; some sort of drive error or door is open, disable paused flag
  1172. ;
  1173.         mov     cs:play_mode[bx],PAUSE_FALSE
  1174.  
  1175. audio_status_info_null:
  1176. ;
  1177. ; return not paused and NULL starting/ending locations
  1178. ;
  1179.         xor     ax,ax
  1180.         mov     word ptr es:io_audio_st_bit[di],ax
  1181.         mov     word ptr es:io_audio_start[di],ax
  1182.         mov     word ptr es:io_audio_start[di+2],ax
  1183.         mov     word ptr es:io_audio_end[di],ax
  1184.         mov     word ptr es:io_audio_end[di+2],ax
  1185.         jmp     short audio_status_info_exit
  1186.  
  1187.  
  1188. ;============================================================
  1189. ;
  1190. ; IOCTL OUTPUT commands...
  1191. ;
  1192. ;============================================================
  1193.  
  1194. ;----------------------------------------------------------------------
  1195. ;
  1196. ; eject
  1197. ;
  1198. ; IOCTL OUTPUT sub-function #0
  1199. ;
  1200. ; Unlock the drive door and eject the disc.
  1201. ;
  1202. ; Note that after successful completion of this command the status bit
  1203. ; in the device status word should report the door as being open until the
  1204. ; user has inserted a disc and closed the door (so the door open bit
  1205. ; can be monitored until this has occurred).
  1206. ;
  1207. ;----------------------------------------------------------------------
  1208. eject:
  1209.  
  1210.         WriteAux <ioctl output eject>
  1211.  
  1212. ;    bx - drive num
  1213. ;
  1214.         call    cdrom_audio_check       ;busy with audio?
  1215.         jnc     @f                      ;  no
  1216.         call    clear_audio_flags       ;  yes, clear pause/play flags
  1217. @@:
  1218.         call    cdrom_eject
  1219.         jc      @f                      ;error occurred? 
  1220.         call    clear_audio_flags       ;no, reset audio flags
  1221.         jmp     ioctl_io_exit
  1222. @@:     jmp     exit                    ;  yes, ax contains status
  1223.  
  1224.  
  1225. ;----------------------------------------------------------------------
  1226. ;
  1227. ; lock_door
  1228. ;
  1229. ; IOCTL OUTPUT sub-function #1
  1230. ;
  1231. ; Unlock/lock the drive door.
  1232. ;
  1233. ;----------------------------------------------------------------------
  1234. lock_door:
  1235.  
  1236.         WriteAux <ioctl output lock door>
  1237.  
  1238. ;    bx - drive num
  1239. ; es:di - lock/unlock code byte (0 - unlock door, 1 - lock door)
  1240. ;
  1241.         mov     al,es:[di]              ;pass user request in al
  1242.         cmp     al,1
  1243.         ja      lock_door_invalid_code
  1244.         call    cdrom_lock_door
  1245.         jc      @f
  1246.         jmp     ioctl_io_exit
  1247.  
  1248. lock_door_invalid_code:
  1249.         mov     ax,(ERRBIT + DONEBIT + drverr_unknown_command)
  1250. @@:     jmp     exit                    ;  yes, ax contains status
  1251.  
  1252.  
  1253. ;----------------------------------------------------------------------
  1254. ;
  1255. ; reset_drive
  1256. ;
  1257. ; IOCTL OUTPUT sub-function #2
  1258. ;
  1259. ; Tell the drive to reset and re-initialize itself.
  1260. ;
  1261. ;----------------------------------------------------------------------
  1262. reset_drive:
  1263.  
  1264.         WriteAux <ioctl output reset drive>
  1265.  
  1266. ;    bx - drive num
  1267. ;
  1268.         call    cdrom_audio_check       ;busy with audio?
  1269.     mov    ax,(ERRBIT + DONEBIT + BUSYBIT + drverr_general_failure)
  1270.         jc      @f                      ;  yes
  1271.         call    cdrom_reset_drive       ;  no, ask for a reset
  1272.         jc      @f                      ;error occurred resetting? 
  1273.         call    clear_audio_flags       ;  no, reset audio variables
  1274.         jmp     ioctl_io_exit
  1275. @@:     jmp     exit                    ;  yes, ax contains status
  1276.  
  1277.  
  1278. ;----------------------------------------------------------------------
  1279. ;
  1280. ; audio_channel_ctrl
  1281. ;
  1282. ; IOCTL OUTPUT sub-function #3
  1283. ;
  1284. ; Control audio channel output.
  1285. ;
  1286. ; Drives that support audio volume control distribute the number of settings
  1287. ; continuously across 256 values (eg. 16 settings become 0, 16, 32, ...).
  1288. ;
  1289. ; Drives than can't swap channels ignore channel swapping unless requested
  1290. ; to play both channels in one, in which case the other is suppressed.
  1291. ;
  1292. ; Drives that don't support four audio channels should ignore setting
  1293. ; specified for the second pair of channels.
  1294. ;
  1295. ;----------------------------------------------------------------------
  1296. audio_channel_ctrl:
  1297.  
  1298.         WriteAux <ioctl output audio channel control>
  1299.  
  1300. ;    bx - drive num
  1301. ; es:di - channel setting parameter block
  1302. ;
  1303. ; get the channel and volume settings
  1304. ;
  1305.         mov     cx,word ptr es:io_ch0_ich[di]
  1306.         mov     dx,word ptr es:io_ch1_ich[di]
  1307.         mov     si,word ptr es:io_ch2_ich[di]
  1308.         mov     di,word ptr es:io_ch3_ich[di]
  1309. ;
  1310. ; parameters to cdrom_audio_channel_ctrl:
  1311. ;
  1312. ; bx - drive num
  1313. ; cl - output channel for input channel 0
  1314. ; ch - channel 0 volume setting
  1315. ; dl - output channel for input channel 1
  1316. ; dh - channel 1 volume setting
  1317. ; si - lo byte = output channel for input channel 2
  1318. ;      hi byte = channel 2 volume
  1319. ; di - lo byte = output channel for input channel 3
  1320. ;      hi byte = channel 3 volume
  1321. ;
  1322.         call    cdrom_audio_channel_ctrl
  1323.         jc      @f                      ;error occurred? 
  1324.         jmp     ioctl_io_exit           ;  no
  1325. @@:     jmp     exit                    ;  yes, ax contains status
  1326.  
  1327.  
  1328. ;----------------------------------------------------------------------
  1329. ;
  1330. ; write_drive_ctrl
  1331. ;
  1332. ; IOCTL OUTPUT sub-function #4
  1333. ;
  1334. ; Write bytes directly to the CD-ROM drive.
  1335. ;
  1336. ; This routine is provided to allow device and/or driver dependent
  1337. ; information (not addressed elsewhere in the MSCDEX device driver spec)
  1338. ; to be sent by an application.
  1339. ;
  1340. ;----------------------------------------------------------------------
  1341. write_drive_ctrl:
  1342.  
  1343.         WriteAux <ioctl output write drive bytes>
  1344.  
  1345. ;    bx - drive num
  1346. ; es:di - channel setting parameter block
  1347. ;
  1348.         call    cdrom_write_drive_ctrl
  1349.         jc      @f                      ;error occurred? 
  1350.         jmp     ioctl_io_exit           ;  no
  1351. @@:     jmp     exit                    ;  yes, ax contains status
  1352.  
  1353.  
  1354. ;----------------------------------------------------------------------
  1355. ;
  1356. ; close_tray
  1357. ;
  1358. ; IOCTL OUTPUT sub-function #5
  1359. ;
  1360. ; Close the drive door.  This is the logical complement to the eject
  1361. ; command (IOCTL OUTPUT sub-function #0)
  1362. ;
  1363. ;----------------------------------------------------------------------
  1364. close_tray:
  1365.  
  1366.         WriteAux <ioctl output close tray>
  1367.  
  1368. ;    bx - drive num
  1369. ;
  1370.         call    cdrom_close_tray
  1371.         jc      @f                      ;error occurred? 
  1372.         jmp     ioctl_io_exit           ;  no
  1373. @@:     jmp     short exit              ;  yes, ax contains status
  1374.  
  1375.  
  1376. ;======================================================================
  1377. ;
  1378. ; input_flush
  1379. ;
  1380. ; INPUT FLUSH, CD-ROM device driver routine requesting the device
  1381. ; driver to free all input buffers and clear any pending requests.
  1382. ;======================================================================
  1383. input_flush:
  1384.  
  1385.         WriteAux <input flush>
  1386.  
  1387.         call    cdrom_input_flush
  1388.         jc      @f                      ;error occurred? 
  1389.         jmp     ioctl_io_exit           ;  no, return done/busy
  1390. @@:     jmp     short exit              ;  yes, ax contains status
  1391.  
  1392.  
  1393. ;======================================================================
  1394. ;
  1395. ; device_open
  1396. ;
  1397. ; DEVICE OPEN, CD-ROM device driver routine indicating to the device
  1398. ; driver that an application is beginning to use it.
  1399. ;
  1400. ;======================================================================
  1401. device_open:
  1402.  
  1403.         WriteAux <device open>
  1404.  
  1405.         inc     cs:opens
  1406.         call    cdrom_device_open
  1407.         jc      @f                      ;error occurred? 
  1408.         jmp     ioctl_io_exit           ;  no, return done/busy
  1409. @@:     jmp     short exit              ;  yes, ax contains status
  1410.  
  1411.  
  1412. ;======================================================================
  1413. ;
  1414. ; device_close
  1415. ;
  1416. ; DEVICE CLOSE, CD-ROM device driver routine indicating to the device
  1417. ; driver that an application is through using it.
  1418. ;
  1419. ;======================================================================
  1420. device_close:
  1421.  
  1422.         WriteAux <device close>
  1423.  
  1424.         dec     cs:opens
  1425.         call    cdrom_device_close
  1426.         jc      @f                      ;error occurred? 
  1427.         jmp     ioctl_io_exit           ;  no, return done/busy
  1428. @@:     jmp     short exit              ;  yes, ax contains status
  1429.  
  1430.  
  1431. ;----------------------------------------------------------------------
  1432. ;
  1433. ; Exit points.
  1434. ;
  1435. ;----------------------------------------------------------------------
  1436.  
  1437. error:
  1438. ;
  1439. ; Exit indicating unknown command error
  1440. ;
  1441.         mov     ax,(ERRBIT + DONEBIT + drverr_unknown_command)
  1442.         jmp     short exit
  1443.  
  1444.  
  1445. exit_busy:
  1446. ;
  1447. ; Exit indicating no errors and audio is playing
  1448. ;
  1449.         mov     ax,(DONEBIT + BUSYBIT)
  1450.         jmp     short exit
  1451.  
  1452.  
  1453. exit_not_busy:
  1454. ;
  1455. ; Exit indicating no errors and audio is not playing
  1456. ;
  1457.         mov     ax,DONEBIT
  1458.  
  1459. exit:
  1460. ;
  1461. ; Exit and poke the status word into the request header.
  1462. ; This is always the final exit point.
  1463. ;
  1464.         lds     bx,dword ptr cs:RequestHeader
  1465.         mov     [bx].rqh_status,ax
  1466.  
  1467. exit_init:
  1468. ;
  1469. ; exit point from INIT
  1470. ;
  1471.         pop     es
  1472.         pop     ds
  1473.         pop     bp
  1474.         pop     di
  1475.         pop     si
  1476.         pop     dx
  1477.         pop     cx
  1478.         pop     bx
  1479.         pop     ax
  1480.         ret
  1481.  
  1482. interrupt  endp
  1483.  
  1484.  
  1485.  
  1486. ;***************************************************************
  1487. ;
  1488. ; Various helper functions
  1489. ;
  1490. ;***************************************************************
  1491.  
  1492.  
  1493.  
  1494. ;---------------------------------------------------------------
  1495. ;
  1496. ; prepare_read_prefetch
  1497. ;
  1498. ; Sets up registers for read_long() and prefetch().
  1499. ;
  1500. ; Entry:
  1501. ;       ds:bx - far ptr to the request header.
  1502. ;
  1503. ; Exit:
  1504. ;       if busy with audio
  1505. ;               exits device driver
  1506. ;       else
  1507. ;               dl:ax - redbook address for read
  1508. ;                  cx - number of sectors to read
  1509. ;               es:bx - transfer address for data
  1510. ;                  dh - drive number (0 based)
  1511. ;                  di - read mode (0 = cooked, 1 = raw) 
  1512. ;               audio paused/playing flag cleared
  1513. ;       
  1514. ;
  1515. ;---------------------------------------------------------------
  1516. prepare_read_prefetch proc near
  1517.  
  1518.         mov     ax,(ERRBIT + DONEBIT + BUSYBIT + drverr_general_failure)
  1519.         call    check_if_busy           ;don't return if busy
  1520. ;
  1521. ; Determine whether cooked or raw mode is selected
  1522. ;
  1523.         xor     ax,ax                   ;assume is cooked mode I/O  (ax = 0)
  1524.         cmp     [si].rwl_mode,IO_COOKED ;cooked mode I/O?
  1525.         je      @f                      ;  yes
  1526.                                         ;  no
  1527.         inc     ax                      ;assume raw mode I/O        (ax = 1)
  1528.         cmp     [si].rwl_mode,IO_RAW    ;raw mode I/O?
  1529.         je      @f                      ;  yes
  1530.         mov     ax,(ERRBIT + DONEBIT + drverr_unknown_command)
  1531.         jmp     exit                    ;  no, illegal mode for I/O
  1532. @@:
  1533.         mov     di,ax                   ;save read mode for below
  1534. ;
  1535. ; Initialize dx:ax to the desired block number
  1536. ;
  1537.         mov     ax,word ptr [si].rwl_sectno.lo
  1538.         mov     dx,word ptr [si].rwl_sectno.hi
  1539.  
  1540.         cmp     [si].rwl_addrmd,MODE_RED;already in redbook addressing mode?
  1541.         je      @f                      ;  yes
  1542.         call    hsg2red                 ;  no, HSG logical sector --> redbook
  1543. @@:
  1544.         mov     cx,[si].rwl_nsects      ;bx = Number of blocks to read
  1545.         les     bx,[si].rwl_xfer        ;es:bx -> buffer
  1546.         mov     dh,byte ptr cs:drive_num
  1547.         call    clear_audio_flags
  1548.         ret
  1549.  
  1550. prepare_read_prefetch endp
  1551.  
  1552.  
  1553. ;---------------------------------------------------------------
  1554. ;
  1555. ; clear_audio_flags
  1556. ;
  1557. ; Resets the paused flag for the drive number passed in bx.
  1558. ;
  1559. ;---------------------------------------------------------------
  1560. clear_audio_flags proc near
  1561.  
  1562.         push    bx
  1563.         mov     bx,cs:drive_num
  1564.         mov     cs:play_mode[bx],PAUSE_FALSE
  1565.         pop     bx
  1566.         ret
  1567.  
  1568. clear_audio_flags endp
  1569.  
  1570.  
  1571. ;---------------------------------------------------------------
  1572. ;
  1573. ; get_current_loc
  1574. ;
  1575. ; Return the current location of the drive head as a HSG sector address.
  1576. ; This must be implemented using the Q-channel since the caller must
  1577. ; be able to expect the successful operation of this routine will not
  1578. ; interrupt audio playing.
  1579. ;
  1580. ; Entry:
  1581. ;   bx - drive number
  1582. ;
  1583. ; Exit:
  1584. ;   trashes bp,cx
  1585. ;   Carry set   - an error occurred
  1586. ;   Carry clear - dx:ax = current HSG logical sector location of drive head.
  1587. ;
  1588. ;---------------------------------------------------------------
  1589. get_current_loc proc near
  1590.  
  1591.         call    cdrom_current_loc       ;pass drive number in di
  1592.         ret
  1593.  
  1594. get_current_loc endp
  1595.  
  1596.  
  1597. ;---------------------------------------------------------------
  1598. ;
  1599. ; get_drive_status
  1600. ;
  1601. ; Return status of the drive.
  1602. ;
  1603. ; Entry:
  1604. ;       bx = drive num   
  1605. ; Exit:
  1606. ;       trashes ax,dx
  1607. ;       carry set -> drive is busy not ready error
  1608. ;
  1609. ;---------------------------------------------------------------
  1610. get_drive_status proc near
  1611.  
  1612.         call    cdrom_drive_status
  1613.         jc      @f
  1614.         mov     cs:play_mode[di],PAUSE_FALSE
  1615. @@:     ret
  1616.  
  1617. get_drive_status endp
  1618.  
  1619.  
  1620.  
  1621. ;----------------------------------------------------------------------
  1622. ; check_if_busy
  1623. ;
  1624. ; This is the preamble to just about every routine.  It points si to the
  1625. ; request header offset and checks if the drive's playing audio.  If not
  1626. ; it returns with the carry flag clear, otherwise it will return with the
  1627. ; carry flag set, or exit the driver, as indicated by ax upon entry.
  1628. ;
  1629. ; Entry:
  1630. ;       es:bx - ptr to request header
  1631. ;          ax - if  0 return to caller on error 
  1632. ;               if !0 exit driver using ax for the status word on error 
  1633. ;
  1634. ; Exit:
  1635. ;       bx - drive number
  1636. ;       si - request header offset
  1637. ;       carry clear if not busy
  1638. ;       carry set   if     busy (returns to caller or exits driver)
  1639. ;
  1640. ;----------------------------------------------------------------------
  1641. check_if_busy proc near
  1642.  
  1643.         mov     si,bx                   ;use the request header in si
  1644.         mov     bx,cs:drive_num         ;do we think we're playing audio?
  1645.         cmp     cs:play_mode[bx],PLAY_TRUE
  1646.         clc
  1647.         je      @f                      ;  yes, make sure the drive agrees
  1648.         ret                             ;  no, tell 'em we're not busy
  1649. @@:
  1650.         push    ax                      ;save status word for if jmp to exit
  1651.         call    cdrom_audio_check
  1652.         pop     ax
  1653.         jc      @f
  1654.         mov     cs:play_mode[bx],PLAY_FALSE
  1655.         ret
  1656. @@:
  1657. ;
  1658. ; we think we're busy with audio, and sure enough, the drive agrees
  1659. ;
  1660.         or      ax,ax                   ;*** EXIT DRIVER ?
  1661.         jnz     @f                      ;  yes, ax = status word
  1662.         stc                             ;  no, return to caller
  1663.         ret
  1664. @@:
  1665.         pop     bx                      ;skip return address
  1666.         jmp     exit                    ;EXIT DRIVER
  1667.  
  1668. check_if_busy endp
  1669.  
  1670.  
  1671. ;----------------------------------------------------------------------
  1672. ; bcd2bin
  1673. ;
  1674. ; Convert BCD to binary representation checking for invalid BCD format.
  1675. ;
  1676. ; Entry:
  1677. ;   al = BCD value (0-99).
  1678. ;   
  1679. ; Exit:
  1680. ;   al          = binary value (0-63h)
  1681. ;
  1682. ;----------------------------------------------------------------------
  1683. bcd2bin proc    near
  1684.  
  1685.         push    bx
  1686.         push    cx
  1687.         mov     bl,al                   
  1688.         mov     ah,al                   ; bl = ah = BCD value to error check
  1689.         and     bl,0fh
  1690.         cmp     bl,09h
  1691.         ja      bad_bcd
  1692.         and     ah,0f0h
  1693.         cmp     ah,090h
  1694.         ja      bad_bcd
  1695.         call    _bcd2bin
  1696.         clc
  1697. @@:
  1698.         xor     ah,ah
  1699.         pop     cx
  1700.         pop     bx
  1701.         ret
  1702. bad_bcd:
  1703.         stc
  1704.         jmp     short @b
  1705.  
  1706. bcd2bin endp
  1707.  
  1708.  
  1709. ;----------------------------------------------------------------------
  1710. ; _bcd2bin
  1711. ;
  1712. ; Convert BCD to binary.
  1713. ;
  1714. ; Entry:
  1715. ;   al = BCD value (0-99).
  1716. ;   
  1717. ; Exit:
  1718. ;   al = binary value (0-63h)
  1719. ;   cx = trashed
  1720. ;
  1721. ;----------------------------------------------------------------------
  1722. _bcd2bin proc near
  1723.  
  1724.         mov     ch,al
  1725.         mov     cl,4
  1726.         shr     al,cl
  1727.         mov     cl,10
  1728.         mul     cl
  1729.         and     ch,0fh
  1730.         add     al,ch
  1731.         ret
  1732.  
  1733. _bcd2bin endp
  1734.  
  1735.  
  1736. ;----------------------------------------------------------------------
  1737. ; bcd2red
  1738. ;
  1739. ; Converts each of the three bytes of the passed redbook address
  1740. ; from BCD to binary representation.
  1741. ;
  1742. ; Entry:
  1743. ;   dh - 0
  1744. ;   dl - BCD min
  1745. ;   ah - BCD sec
  1746. ;   al - BCD frame
  1747. ;
  1748. ; Exit:
  1749. ;   dh - 0
  1750. ;   dl - binary min
  1751. ;   ah - binary  sec
  1752. ;   al - binary  frame
  1753. ;
  1754. ;----------------------------------------------------------------------
  1755. bcd2red proc near
  1756.  
  1757.         push    cx
  1758.         mov     cx,ax
  1759.         xor     ah,ah                   ; al = frame
  1760.         call    bcd2bin
  1761.         mov     cl,al
  1762.         mov     al,ch                   ; al = sec
  1763.         call    bcd2bin
  1764.         mov     ch,al                   ; cx = sec,,frame
  1765.         mov     al,dl                   ; al = min
  1766.         call    bcd2bin
  1767.         mov     dx,ax                   ; dl = min
  1768.         mov     ax,cx
  1769.         pop     cx
  1770.         ret
  1771.  
  1772. bcd2red endp
  1773.  
  1774.  
  1775. ;----------------------------------------------------------------------
  1776. ; red2hsg
  1777. ;
  1778. ; Converts the passed (binary) redbook address into an HSG address.
  1779. ;
  1780. ; Entry:
  1781. ;       dh - 0
  1782. ;       dl - binary min
  1783. ;       ah - binary sec
  1784. ;       al - binary frame
  1785. ;
  1786. ; Exit:
  1787. ;       dx:ax contains HSG address (pure binary frame number less lead-in).
  1788. ;
  1789. ;----------------------------------------------------------------------
  1790. red2hsg proc    near
  1791.  
  1792.         push    bx
  1793.         mov     bx,ax                   ;save (sec:frame)
  1794.         mov     al,dl                   ;al = min
  1795.         mov     cl,60
  1796.         mul     cl                      ;ax = min*60
  1797.         add     al,bh
  1798.         adc     ah,0                    ;ax = min*60 + sec
  1799.         mov     cx,75
  1800.         mul     cx                      ;dx:ax = (min*60 + sec)*75
  1801.         xor     bh,bh
  1802.         add     ax,bx
  1803.         adc     dx,0                    ;dx:ax = (min*60 + sec)*75 + frame
  1804.         sub     ax,150
  1805.         sbb     dx,0                    ;dx:ax = HSG address
  1806.         pop     bx
  1807.         ret
  1808.  
  1809. red2hsg endp
  1810.  
  1811.  
  1812. ;----------------------------------------------------------------------
  1813. ; hsg2red
  1814. ;
  1815. ; Converts passed HSG address into redbook address.
  1816. ;
  1817. ; Entry:
  1818. ;       dx:ax contains HSG address (logical sector number less lead-in area).
  1819. ;
  1820. ; Exit:
  1821. ;       dh - 0
  1822. ;       dl - binary min
  1823. ;       ah - binary sec
  1824. ;       al - binary frame
  1825. ;
  1826. ;----------------------------------------------------------------------
  1827. hsg2red proc    near
  1828.  
  1829.         push    cx
  1830.         add     ax,150                  ;Add lead-in area
  1831.         adc     dx,0
  1832.         mov     cx,60*75
  1833.         div     cx                      ;ax = minutes, dx = fraction of minutes
  1834.         xchg    dx,ax                   ;dx = minutes
  1835.         mov     cl,75                   
  1836.         div     cl                      ;al = seconds, ah = frames
  1837.         xchg    ah,al                   ;ah = seconds, al = frames
  1838.         pop     cx
  1839.         ret
  1840.  
  1841. hsg2red endp
  1842.  
  1843.  
  1844. _TEXT ends
  1845.  
  1846. ;***************************************************************
  1847. ;
  1848. ; resident code/data ends here, note this module should be first
  1849. ; in the link (to start at an offset address of 0)
  1850. ;
  1851. ;
  1852. ; code/data below here is for init time only
  1853. ;
  1854. ;***************************************************************
  1855.  
  1856. _LAST   segment para public 'last'
  1857.         assume  cs:_LAST
  1858.  
  1859. very_end label byte
  1860.  
  1861. ;foobar macro   y
  1862. ;if2
  1863. ;    %out Resident size of driver is y
  1864. ;endif
  1865. ;endm
  1866. ;
  1867. ;foobar %(offset very_end)
  1868.  
  1869.  
  1870. ;======================================================================
  1871. ;
  1872. ; init
  1873. ;
  1874. ; INIT, CD-ROM device driver routine to initialize the driver.
  1875. ;
  1876. ; This is the only device driver call coming directly from DOS, and is
  1877. ; only made once.  init should initialize certain fields in the request
  1878. ; header:
  1879. ;
  1880. ; - Set init_units and init_devno to 0 since DOS views this as a character
  1881. ; device (MSCDEX makes its own determination of the number of units through
  1882. ; the device header).
  1883. ;
  1884. ; - Return the address of the end of the resident code/data section in
  1885. ;   init_endaddr.  Code/data after this pointer is discarded.
  1886. ;
  1887. ; - Parse the CONFIG.SYS line after the '=' character (pointed to by
  1888. ; init_bpbarr) for the device name and fill in the dev_name field in
  1889. ; the device header making sure it is a legal 8-character filename
  1890. ; (padded out to 8 characters with spaces if necessary).  
  1891. ;
  1892. ; Entry:
  1893. ;   ds:bx - far ptr to the request header
  1894. ;       InitHeader    struc
  1895. ;
  1896. ;       init_rqh        db  size Request_Hdr dup (?)
  1897. ;       init_units      db  ?
  1898. ;       init_endaddr    dd  ?
  1899. ;       init_bpbarr     dd  ?
  1900. ;       init_devno      db  ?
  1901. ;       InitHeader    ends
  1902. ;
  1903. ;======================================================================
  1904.  
  1905. init proc far
  1906.  
  1907.         call    cdrom_init
  1908.         jmp     far ptr exit_init
  1909.  
  1910. init endp
  1911.  
  1912. _LAST   ends
  1913.  
  1914. ifdef DEBUG
  1915.  
  1916.         public  very_top
  1917.         public  DriverFuncs
  1918.         public  IOCTLInput
  1919.         public  IOCTLOutput
  1920.  
  1921.         public  strategy
  1922.         public  interrupt
  1923.         public  read_long
  1924.         public  prefetch
  1925.         public  seek
  1926.         public  play_audio
  1927.         public  stop_audio
  1928.         public  resume_audio
  1929.         public  ioctl_output
  1930.         public  ioctl_input
  1931.         public  return_address
  1932.         public  audio_channel_info
  1933.         public  location_head
  1934.         public  read_drive_bytes
  1935.         public  device_status
  1936.         public  sector_size
  1937.         public  volume_size
  1938.         public  media_changed
  1939.         public  audio_diskinfo
  1940.         public  audio_trackinfo
  1941.         public  audio_Qchannel
  1942.         public  upc_code
  1943.         public  audio_status_info
  1944.         public  eject
  1945.         public  lock_door
  1946.         public  reset_drive
  1947.         public  audio_channel_ctrl
  1948.         public  write_drive_ctrl
  1949.         public  close_tray
  1950.         public  input_flush
  1951.         public  device_open
  1952.         public  device_close
  1953.  
  1954. endif  ;DEBUG
  1955.  
  1956.         end
  1957.  
  1958.